﻿//
// Copyright © MixModes Inc. 2011
//

using System;
using System.Windows;
using System.Windows.Data;
using MixModes.Phone.Synergy.Utilities;

namespace MixModes.Phone.Synergy.Framework
{
    /// <summary>
    /// Observes value change for Bindings
    /// </summary>
    public class ObservableBinding : DependencyObject
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ObservableBinding"/> class.
        /// </summary>
        public ObservableBinding()
        {
            _changeTrackerProperty = DependencyProperty.RegisterAttached("ChangeTracker",
                                                                         typeof(object),
                                                                         typeof(ObservableBinding),
                                                                         new PropertyMetadata(null, OnPropertyChanged));
        }

        /// <summary>
        /// Attaches the specified binding.
        /// </summary>
        /// <param name="binding">The binding.</param>
        /// <param name="target">The target.</param>
        public void Attach(Binding binding, FrameworkElement target)
        {
            Validate.NotNull(binding, "binding");
            Validate.NotNull(target, "target");
            Validate.Assert<InvalidOperationException>(_target == null);
            _target = target;            
            _target.SetBinding(_changeTrackerProperty, binding);
        }

        /// <summary>
        /// Detaches this instance.
        /// </summary>
        public void Detach()
        {
            if (_target == null)
            {
                return;
            }

            _target.ClearValue(_changeTrackerProperty);
            _target = null;
            _value = null;
        }

        /// <summary>
        /// Gets the value.
        /// </summary>
        /// <value>The value.</value>
        public object Value
        {
            get { return _value; }
        }        

        /// <summary>
        /// Called when property has changed due to change in Binding's value
        /// </summary>
        /// <param name="d">The d.</param>
        /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
        private void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            _value = e.NewValue;
        }

        // Private members
        private DependencyProperty _changeTrackerProperty;
        private FrameworkElement _target;
        private object _value;
    }
}
